package cn.openea.perpartner.common.auth.util;

import cn.openea.perpartner.common.auth.entity.LoginBody;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;


/**
 * @author Weird077
 * @description TODO
 * @date 2022-07-18 10:45
 */
public class JedisUtil {
    private static String host;
    private static int port;
    private static String pwd;
    private static int db = 0;
    private static ShardedJedisPool shardedJedisPool;
    private static ReentrantLock lock = new ReentrantLock(false);
    public static void init(String host,int port,String pwd) {
        JedisUtil.host = host;
        JedisUtil.port = port;
        JedisUtil.pwd = pwd;
        getInstance();
    }
    public static void init(String host,int port,int db,String pwd) {
        JedisUtil.host = host;
        JedisUtil.port = port;
        JedisUtil.db = db;
        JedisUtil.pwd = pwd;
        getInstance();
    }

    /**
     * 获取ShardedJedis实例
     * @return
     */
    private static ShardedJedis getInstance() {
        if (shardedJedisPool == null) {
            try {
                if (lock.tryLock(2, TimeUnit.SECONDS)) {
                    try {
                        // JedisPoolConfig
                        JedisPoolConfig config = new JedisPoolConfig();
                        config.setMaxTotal(200);
                        config.setMaxIdle(50);
                        config.setMinIdle(0);
                        config.setMaxWaitMillis(-1);

                        JedisShardInfo jedisShardInfo = new JedisShardInfo(host,port);
                        //设置密码
                        jedisShardInfo.setPassword(pwd);
                        //通过反射，修改db
                        Class<? extends JedisShardInfo> clz = jedisShardInfo.getClass();
                        Field field = clz.getDeclaredField("db");
                        field.setAccessible(true);
                        field.set(jedisShardInfo,db);
                        List<JedisShardInfo> shardInfoList = new LinkedList<>();
                        shardInfoList.add(jedisShardInfo);
                        shardedJedisPool = new ShardedJedisPool(config, shardInfoList);

                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    } finally {
                        lock.unlock();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (shardedJedisPool == null) {
            throw new NullPointerException("JedisUtil.ShardedJedisPool is null.");
        }
        return shardedJedisPool.getResource();
    }

    public static void close() {
        if (shardedJedisPool != null) {
            shardedJedisPool.close();
        }
    }

    /**
     * 将对象-->byte[] (由于jedis中不支持直接存储object所以转换成byte[]存入)
     * @return
     */
    public static  byte[] serialize(Object t)
    {
        if (t == null)
        {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
    }


    /**
     * 将byte[] -->Object
     * @param bytes
     * @return
     */
    public static Object unserialize(byte[] bytes)
    {
        if (bytes == null || bytes.length <= 0)
        {
            return null;
        }
        String str = new String(bytes, StandardCharsets.UTF_8);

        return JSON.parseObject(str, LoginBody.class);
    }

    /**
     * Set Object
     * @param key
     * @param obj
     * @param seconds 存活时间,单位/秒
     */
    public static String setObjectValue(String key, Object obj, int seconds) {
        String result = null;
        ShardedJedis client = getInstance();
        try {
            result = client.setex(key.getBytes(), seconds, serialize(obj));
        } catch (Exception e) {
            e.printStackTrace();
        }
        client.close();
        return result;
    }

    /**
     * Get Object
     * @param key
     * @return
     */
    public static Object getObjectValue(String key) {
        Object obj = null;
        ShardedJedis client = getInstance();
        try {
            byte[] bytes = client.get(key.getBytes());
            if (bytes != null && bytes.length > 0) {
                obj = unserialize(bytes);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        client.close();
        return obj;
    }

    /**
     * Delete key
     * @param key
     * @return Integer reply, specifically:
     * an integer greater than 0 if one or more keys were removed
     * 0 if none of the specified key existed
     */
    public static Long delete(String key) {
        Long result = null;
        ShardedJedis client = getInstance();
        try {
            result = client.del(key);
        } catch (Exception e) {
            e.printStackTrace();
        }
        client.close();
        return result;
    }





}